package com.kanche.bigbaby.collection.domain;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

public class WordChecker {
	private static WordChecker instance;

	private TrieNode rootNode;

	class TrieNode {
		public Map<Character, TrieNode> getTable() {
			return table;
		}

		public void setTable(Map<Character, TrieNode> table) {
			this.table = table;
		}

		public Character getCh() {
			return ch;
		}

		public void setCh(Character ch) {
			this.ch = ch;
		}

		public Boolean getTerminate() {
			return terminate;
		}

		public void setTerminate(Boolean terminate) {
			this.terminate = terminate;
		}

		Map<Character, TrieNode> table;
		Character ch;
		Boolean terminate;

		TrieNode(Character ch, Boolean terminate) {
			this.table = new HashMap<Character, TrieNode>();
			this.ch = ch;
			this.terminate = terminate;
		}

		public TrieNode findChild(Character ch) {
			return this.table.get(ch);
		}

		public void addChild(Character ch, TrieNode child) {
			this.table.put(ch, child);
		}

		public void removeChild(TrieNode child) {
			this.table.remove(child.getCh());
		}

		public void clearChild() {
			this.table.clear();
		}
	}

	public static class CheckResult {
		Boolean ok;
		int offset;

		public Boolean getOk() {
			return ok;
		}

		public void setOk(Boolean ok) {
			this.ok = ok;
		}

		public int getOffset() {
			return offset;
		}

		public void setOffset(int offset) {
			this.offset = offset;
		}

		public int getLen() {
			return len;
		}

		public void setLen(int len) {
			this.len = len;
		}

		int len;

		CheckResult(Boolean ok, int offset, int len) {
			this.ok = ok;
			this.offset = offset;
			this.len = len;
		}
	}

	private int matchWord(String word, TrieNode node, int length) {
		if (word == null) {
			return 0;
		}
        if(word.isEmpty()){
            return 0;
        }

		Character firstChar = word.charAt(0);
		String restWord = word.substring(1);

		TrieNode child = node.findChild(firstChar);

		if (child != null) {
			if (child.getTerminate()) {
				return length + 1;
			}
			return matchWord(restWord, child, (length + 1));
		} else {
			return 0;
		}
	}

	private int matchContent(String content) {
		return matchWord(content, this.rootNode, 0);
	}

	/*private CheckResult check(String content, int offset) {
		if (content.isEmpty()) {
			return new CheckResult(true, 0, 0);
		}

		int length = matchContent(content);
		if (length > 0) {
			return new CheckResult(false, offset, length);
		}
		String restContent = content.substring(1);
		return check(restContent, (offset + 1));
	}

	public CheckResult check(String content) {
		if (content == null) {
			return new CheckResult(true, 0, 0);
		}

		if (content.isEmpty()) {
			return new CheckResult(true, 0, 0);
		}

		return check(content, 0);
	}*/

	public CheckResult check(String content) {
		if (content == null) {
			return new CheckResult(true, 0, 0);
		}

		if (content.isEmpty()) {
			return new CheckResult(true, 0, 0);
		}
		
		for (int offset = 0; offset < content.length(); offset ++) {
			String subContent = content.substring(offset);
			int length = matchContent(subContent);
			if (length > 0) {
				return new CheckResult(false, offset, length);
			}
		}
		return new CheckResult(true, 0, 0);
	}
	
	private TrieNode tryAddWord(String word, TrieNode node) {
		TrieNode child;

		if ((word == null) || word.isEmpty()) {
			node.setTerminate(true);
			return null;
		}

		Character firstChar = word.charAt(0);
		String restWord = word.substring(1);

		child = node.getTable().get(firstChar);

		if (child != null) {
			return tryAddWord(restWord, child);
		} else {
			TrieNode newChild = new TrieNode(firstChar, false);
			node.getTable().put(firstChar, newChild);
			return tryAddWord(restWord, newChild);
		}
	}

	public Boolean addWord(String word) {
		if (word.isEmpty()) {
			return false;
		}
		TrieNode node = tryAddWord(word, this.rootNode);
		if (node != null) {
			return true;
		} else {
			return false;
		}
	}

	private WordChecker() {
		InputStream fis;
		BufferedReader br;
		String word;

		this.rootNode = new TrieNode(' ', false);

		try {
			fis = new FileInputStream(
					"/Users/triplex/Source/eclipse/WordChecker/src/wl.txt");
			br = new BufferedReader(new InputStreamReader(fis,
					Charset.forName("UTF-8")));
			while ((word = br.readLine()) != null) {
				addWord(word);
			}
			br.close();
			br = null;
			fis = null;
		} catch (Exception e) {
			System.out.println("read file error " + e.getMessage());
		}
	}

	public static WordChecker getInstance() {
		if (instance == null) {
			instance = new WordChecker();
		}
		return instance;
	}
}